﻿using CommunityToolkit.Mvvm.ComponentModel;
using Company.Core.Helpers;
using Company.Core.Logger;
using Company.Database.Entities;
using Company.Plc;
using Company.Shell.Enums;
using Company.Shell.Extensions;
using Company.Shell.Interfaces;
using LiveCharts;
using LiveCharts.Defaults;
using System.Collections;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Text;

namespace Company.Shell.Models
{
    /// <summary>
    /// 表示一个房间
    /// </summary>
    public class RoomEntity : ObservableObject
    {
        public event Action<AlarmEntity> OnAlarm;
        public IPlc Plc { get; }
        private IConfigProvider ConfigProvider { get; }
        private RoomEntity() { }
        public RoomEntity(IPlc plc,IConfigProvider configProvider)
        {
            Plc = plc;
            ConfigProvider = configProvider;
            Init();
            Alarm();
        }

        /// <summary>
        /// 开启房间报警线程
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private void Alarm()
        {
            Task.Run(() =>
            {
                Thread.Sleep(1000);
                while (true)
                {
                    DoAlarm(27, Value27.OriginValue);
                    DoAlarm(28, Value27.OriginValue);
                    DoAlarm(29, Value27.OriginValue);
                    Thread.Sleep(1000);
                }
            });
        }

        /// <summary>
        /// 处理某个寄存器报警
        /// </summary>
        /// <param name="addressNumber"></param>
        /// <param name="value"></param>
        private void DoAlarm(int addressNumber, ushort value)
        {
            //27  ->  27.00  27.01  27.15
            BitArray array = new BitArray(BitConverter.GetBytes(value));
            for (int i = 0; i < array.Length; i++)
            {
                string address = AlarmItem.GetAddress(addressNumber, i); //27.00
                if (array[i] == true)
                {
                    var entity = AlarmEntities.FirstOrDefault(t => t.AddressNumber == address && t.Status == 1);
                    if (entity == null)
                    {
                        //生成一条当前报警信息
                        entity = new AlarmEntity
                        {
                            RoomNumber = Id,
                            AddressNumber = address,
                            Status =1,
                            AlarmTime = DateTime.Now,
                        };

                        //报警描述
                        AlarmItem alarmItem = ConfigProvider.AlarmItems.FirstOrDefault(t => t.Address == address);
                        if (alarmItem!=null)
                        {
                            entity.Message = alarmItem.Description;
                        }
                        try
                        {
                            //显示到UI
                            System.Windows.Application.Current?.Dispatcher.Invoke(() => AlarmEntities.Add(entity));
                        }
                        catch (Exception ex)
                        {
                            Logs.Error(ex);
                        }
                        
                    }
                }
                else
                {
                    //等于false，判断当前报警记录是否AlarmEntities中，如存在，则修改status状态为0
                    //表示当前报警已恢复，形成一条完整的历史报警记录，写入到数据库中
                    var entity = AlarmEntities.FirstOrDefault(t => t.AddressNumber == address && t.Status == 1);
                    if (entity != null)
                    {
                        //从当前报警UI中移除
                        try
                        {
                            System.Windows.Application.Current?.Dispatcher.Invoke(() => AlarmEntities.Remove(entity));

                        }
                        catch(Exception ex)
                        {
                            Logs.Error($"{ex.Message}");
                        }
                        OnAlarm?.Invoke(entity);//事件通知：插入一条当前报警信息到数据库中
                    }
                }

            }
        }

        private void Init()
        {
            Values.Add(Value0);
            Values.Add(Value1);
            Values.Add(Value2);
            Values.Add(Value3);
            Values.Add(Value4);
            Values.Add(Value5);
            Values.Add(Value6);
            Values.Add(Value7);
            Values.Add(Value8);
            Values.Add(Value9);
            Values.Add(Value10);
            Values.Add(Value11);
            Values.Add(Value12);
            Values.Add(Value13);
            Values.Add(Value14);
            Values.Add(Value15);
            Values.Add(Value16);
            Values.Add(Value17);
            Values.Add(Value18);
            Values.Add(Value19);
            Values.Add(Value20);
            Values.Add(Value21);
            Values.Add(Value22);
            Values.Add(Value23);
            Values.Add(Value24);
            Values.Add(Value25);
            Values.Add(Value26);
            Values.Add(Value27);
            Values.Add(Value28);
            Values.Add(Value29);
            Values.Add(Value30);
            Values.Add(Value31);
            Values.Add(Value32);
            Values.Add(Value33);
            Values.Add(Value34);
            Values.Add(Value35);
            Values.Add(Value36);
            Values.Add(Value37);
            Values.Add(Value38);
            Values.Add(Value39);
            Values.Add(Value40);
            Values.Add(Value41);
            Values.Add(Value42);
            Values.Add(Value43);
            Values.Add(Value44);
            Values.Add(Value45);
            Values.Add(Value46);
            Values.Add(Value47);
            Values.Add(Value48);
            Values.Add(Value49);
            Values.Add(Value50);
            Values.Add(Value51);
            Values.Add(Value52);
            Values.Add(Value53);
            Values.Add(Value54);
            Values.Add(Value55);
            Values.Add(Value56);
            Values.Add(Value57);
            Values.Add(Value58);
            Values.Add(Value59);
            Values.Add(Value60);
            Values.Add(Value61);
            Values.Add(Value62);
            Values.Add(Value63);
            Values.Add(Value64);
            Values.Add(Value65);
            Values.Add(Value66);
            Values.Add(Value67);
            Values.Add(Value68);
            Values.Add(Value69);
            Values.Add(Value70);
            Values.Add(Value71);
            Values.Add(Value72);
            Values.Add(Value73);
            Values.Add(Value74);
            Values.Add(Value75);
            Values.Add(Value76);
            Values.Add(Value77);
            Values.Add(Value78);
            Values.Add(Value79);
            Values.Add(Value80);
            Values.Add(Value81);
            Values.Add(Value82);
            Values.Add(Value83);
            Values.Add(Value84);
            Values.Add(Value85);
            Values.Add(Value86);
            Values.Add(Value87);
            Values.Add(Value88);
            Values.Add(Value89);
            Values.Add(Value90);
            Values.Add(Value91);
            Values.Add(Value92);
            Values.Add(Value93);
            Values.Add(Value94);
            Values.Add(Value95);
            Values.Add(Value96);
            Values.Add(Value97);
            Values.Add(Value98);
            Values.Add(Value99);
        }

        public int Id { get; set; }
        public string Name { get; set; }
        /// <summary>
        /// 房间D区寄存器起始地址，每个房间100个寄存器
        /// </summary>
        public ushort Address { get; set; } = 1000;
        private ProgramEntity? program;
        /// <summary>
        /// 当前房间运行的程序
        /// </summary>
        public ProgramEntity? Program
        {
            get => program;
            set 
            { 
                SetProperty(ref program, value);
                SetEnabled((roomMode, value));
            }
        }
        private RoomParameter roomParameter = new();
        /// <summary>
        /// 房间参数
        /// </summary>
        public RoomParameter RoomParameter
        {
            get => roomParameter;
            set => SetProperty(ref roomParameter, value);
        }
        private DateTime startTime = DateTime.MinValue;
        /// <summary>
        /// 开始运行时间
        /// </summary>
        public DateTime StartTime
        {
            get => startTime; 
            set => SetProperty(ref startTime, value);
        }
        private DateTime endTime = DateTime.MinValue;
        /// <summary>
        /// 结束运行时间
        /// </summary>
        public DateTime EndTime
        {
            get => endTime;
            set => SetProperty(ref endTime, value);
        }
        private TimeSpan totalTime;
        /// <summary>
        /// 运行总时长
        /// </summary>
        public TimeSpan TotalTime
        {
            get => totalTime;
            set=>SetProperty(ref totalTime, value);
        }
        private RoomMode roomMode = RoomMode.Stopping;
        /// <summary>
        /// 房间模式
        /// </summary>
        public RoomMode RoomMode
        {
            get => roomMode;
            set
            {
                SetProperty(ref roomMode, value);
                SetEnabled((value, program));
            }
        }
        private double percent = 100;
        /// <summary>
        /// 房间运行百分比
        /// </summary>
        public double Percent
        {
            get => percent;
            set => SetProperty(ref percent, value);
        }
        private bool isEnabled = false;
        /// <summary>
        /// 开始按钮是否可用
        /// </summary>
        public bool IsEnabled
        {
            get => isEnabled;
            set => SetProperty(ref isEnabled, value);
        }
        private CacheEntity cache = new CacheEntity();
        /// <summary>
        /// 缓存数据
        /// </summary>
        public CacheEntity Cache
        {
            get => cache;
            set=> SetProperty(ref cache, value);
        }

        private TimeSpan timeSpan = new TimeSpan();
        /// <summary>
        /// X轴时间在缓存中的偏移量
        /// </summary>
        public TimeSpan OffsetTime
        {
            get => timeSpan;
            set=>SetProperty(ref timeSpan, value);  
        }

        private ObservableCollection<AlarmEntity> alarmEntities = new();
        /// <summary>
        /// 房间当前报警记录
        /// </summary>
        public ObservableCollection<AlarmEntity> AlarmEntities
        {
            get => alarmEntities;
            set => SetProperty(ref alarmEntities, value);
        }

        /// <summary>
        /// 设置按钮可用状态
        /// </summary>
        /// <param name="p"></param>
        private void SetEnabled((RoomMode, ProgramEntity?) p)
        {
            if (p.Item1 != RoomMode.Stopping || p.Item2 == null)
            {
                IsEnabled = false;
            }
            else
            {
                IsEnabled = true;
            }
        }
        #region 100个点位
        public PlcValue Value0 { get; set; } = new PlcValue(0);

        public PlcValue Value1 { get; set; } = new PlcValue(1);

        public PlcValue Value2 { get; set; } = new PlcValue(2);

        public PlcValue Value3 { get; set; } = new PlcValue(3);

        public PlcValue Value4 { get; set; } = new PlcValue(4);

        public PlcValue Value5 { get; set; } = new PlcValue(5);

        public PlcValue Value6 { get; set; } = new PlcValue(6);

        public PlcValue Value7 { get; set; } = new PlcValue(7);

        public PlcValue Value8 { get; set; } = new PlcValue(8);

        public PlcValue Value9 { get; set; } = new PlcValue(9);

        public PlcValue Value10 { get; set; } = new PlcValue(10);

        public PlcValue Value11 { get; set; } = new PlcValue(11);

        public PlcValue Value12 { get; set; } = new PlcValue(12);

        public PlcValue Value13 { get; set; } = new PlcValue(13);

        public PlcValue Value14 { get; set; } = new PlcValue(14);

        public PlcValue Value15 { get; set; } = new PlcValue(15);

        public PlcValue Value16 { get; set; } = new PlcValue(16);

        public PlcValue Value17 { get; set; } = new PlcValue(17);

        public PlcValue Value18 { get; set; } = new PlcValue(18);

        public PlcValue Value19 { get; set; } = new PlcValue(19);

        public PlcValue Value20 { get; set; } = new PlcValue(20);

        public PlcValue Value21 { get; set; } = new PlcValue(21);

        public PlcValue Value22 { get; set; } = new PlcValue(22);

        public PlcValue Value23 { get; set; } = new PlcValue(23);

        public PlcValue Value24 { get; set; } = new PlcValue(24);

        public PlcValue Value25 { get; set; } = new PlcValue(25);

        public PlcValue Value26 { get; set; } = new PlcValue(26);

        public PlcValue Value27 { get; set; } = new PlcValue(27);

        public PlcValue Value28 { get; set; } = new PlcValue(28);

        public PlcValue Value29 { get; set; } = new PlcValue(29);

        public PlcValue Value30 { get; set; } = new PlcValue(30);

        public PlcValue Value31 { get; set; } = new PlcValue(31);

        public PlcValue Value32 { get; set; } = new PlcValue(32);

        public PlcValue Value33 { get; set; } = new PlcValue(33);

        public PlcValue Value34 { get; set; } = new PlcValue(34);

        public PlcValue Value35 { get; set; } = new PlcValue(35);

        public PlcValue Value36 { get; set; } = new PlcValue(36);

        public PlcValue Value37 { get; set; } = new PlcValue(37);

        public PlcValue Value38 { get; set; } = new PlcValue(38);

        public PlcValue Value39 { get; set; } = new PlcValue(39);

        public PlcValue Value40 { get; set; } = new PlcValue(40);

        public PlcValue Value41 { get; set; } = new PlcValue(41);

        public PlcValue Value42 { get; set; } = new PlcValue(42);

        public PlcValue Value43 { get; set; } = new PlcValue(43);

        public PlcValue Value44 { get; set; } = new PlcValue(44);

        public PlcValue Value45 { get; set; } = new PlcValue(45);

        public PlcValue Value46 { get; set; } = new PlcValue(46);

        public PlcValue Value47 { get; set; } = new PlcValue(47);

        public PlcValue Value48 { get; set; } = new PlcValue(48);

        public PlcValue Value49 { get; set; } = new PlcValue(49);

        public PlcValue Value50 { get; set; } = new PlcValue(50);

        public PlcValue Value51 { get; set; } = new PlcValue(51);

        public PlcValue Value52 { get; set; } = new PlcValue(52);

        public PlcValue Value53 { get; set; } = new PlcValue(53);

        public PlcValue Value54 { get; set; } = new PlcValue(54);

        public PlcValue Value55 { get; set; } = new PlcValue(55);

        public PlcValue Value56 { get; set; } = new PlcValue(56);

        public PlcValue Value57 { get; set; } = new PlcValue(57);

        public PlcValue Value58 { get; set; } = new PlcValue(58);

        public PlcValue Value59 { get; set; } = new PlcValue(59);

        public PlcValue Value60 { get; set; } = new PlcValue(60);

        public PlcValue Value61 { get; set; } = new PlcValue(61);

        public PlcValue Value62 { get; set; } = new PlcValue(62);

        public PlcValue Value63 { get; set; } = new PlcValue(63);

        public PlcValue Value64 { get; set; } = new PlcValue(64);

        public PlcValue Value65 { get; set; } = new PlcValue(65);

        public PlcValue Value66 { get; set; } = new PlcValue(66);

        public PlcValue Value67 { get; set; } = new PlcValue(67);

        public PlcValue Value68 { get; set; } = new PlcValue(68);

        public PlcValue Value69 { get; set; } = new PlcValue(69);

        public PlcValue Value70 { get; set; } = new PlcValue(70);

        public PlcValue Value71 { get; set; } = new PlcValue(71);

        public PlcValue Value72 { get; set; } = new PlcValue(72);

        public PlcValue Value73 { get; set; } = new PlcValue(73);

        public PlcValue Value74 { get; set; } = new PlcValue(74);

        public PlcValue Value75 { get; set; } = new PlcValue(75);

        public PlcValue Value76 { get; set; } = new PlcValue(76);

        public PlcValue Value77 { get; set; } = new PlcValue(77);

        public PlcValue Value78 { get; set; } = new PlcValue(78);

        public PlcValue Value79 { get; set; } = new PlcValue(79);

        public PlcValue Value80 { get; set; } = new PlcValue(80);

        public PlcValue Value81 { get; set; } = new PlcValue(81);

        public PlcValue Value82 { get; set; } = new PlcValue(82);

        public PlcValue Value83 { get; set; } = new PlcValue(83);

        public PlcValue Value84 { get; set; } = new PlcValue(84);

        public PlcValue Value85 { get; set; } = new PlcValue(85);

        public PlcValue Value86 { get; set; } = new PlcValue(86);

        public PlcValue Value87 { get; set; } = new PlcValue(87);

        public PlcValue Value88 { get; set; } = new PlcValue(88);

        public PlcValue Value89 { get; set; } = new PlcValue(89);

        public PlcValue Value90 { get; set; } = new PlcValue(90);

        public PlcValue Value91 { get; set; } = new PlcValue(91);

        public PlcValue Value92 { get; set; } = new PlcValue(92);

        public PlcValue Value93 { get; set; } = new PlcValue(93);

        public PlcValue Value94 { get; set; } = new PlcValue(94);

        public PlcValue Value95 { get; set; } = new PlcValue(95);

        public PlcValue Value96 { get; set; } = new PlcValue(96);

        public PlcValue Value97 { get; set; } = new PlcValue(97);

        public PlcValue Value98 { get; set; } = new PlcValue(98);

        public PlcValue Value99 { get; set; } = new PlcValue(99);

        public List<PlcValue> Values { get; set; } = new List<PlcValue>();

        #endregion

        #region 12个数字量的曲线

        private ChartValues<ObservablePoint> line0 = new();
        public ChartValues<ObservablePoint> Line0
        {
            get => line0;
            set => SetProperty(ref  line0, value);
        }

        private ChartValues<ObservablePoint> line1 = new();
        public ChartValues<ObservablePoint> Line1
        {
            get => line1;
            set => SetProperty(ref line1, value);
        }
        private ChartValues<ObservablePoint> line2 = new();
        public ChartValues<ObservablePoint> Line2
        {
            get => line2;
            set => SetProperty(ref line2, value);
        }
        private ChartValues<ObservablePoint> line3 = new();
        public ChartValues<ObservablePoint> Line3
        {
            get => line3;
            set => SetProperty(ref line3, value);
        }
        private ChartValues<ObservablePoint> line4 = new();
        public ChartValues<ObservablePoint> Line4
        {
            get => line4;
            set => SetProperty(ref line4, value);
        }
        private ChartValues<ObservablePoint> line5 = new();
        public ChartValues<ObservablePoint> Line5
        {
            get => line5;
            set => SetProperty(ref line5, value);
        }
        private ChartValues<ObservablePoint> line6 = new();
        public ChartValues<ObservablePoint> Line6
        {
            get => line6;
            set => SetProperty(ref line6, value);
        }
        private ChartValues<ObservablePoint> line7 = new();
        public ChartValues<ObservablePoint> Line7
        {
            get => line7;
            set => SetProperty(ref line7, value);
        }
        private ChartValues<ObservablePoint> line8 = new();
        public ChartValues<ObservablePoint> Line8
        {
            get => line8;
            set => SetProperty(ref line8, value);
        }
        private ChartValues<ObservablePoint> line9 = new();
        public ChartValues<ObservablePoint> Line9
        {
            get => line9;
            set => SetProperty(ref line9, value);
        }
        private ChartValues<ObservablePoint> line10 = new();
        public ChartValues<ObservablePoint> Line10
        {
            get => line10;
            set => SetProperty(ref line10, value);
        }
        private ChartValues<ObservablePoint> line11 = new();
        public ChartValues<ObservablePoint> Line11
        {
            get => line11;
            set => SetProperty(ref line11, value);
        }
        #endregion


        ushort temperatureValue;
        ushort humidityValue;
        bool newCurve;

        /// <summary>
        /// 开始运行
        /// </summary>
        /// <returns></returns>
        public async Task RunAsync(DateTime? _startTime = null)
        {
            if (Program == null) return;

            //计算时间
            var temperatures = Program.Temperatures as IList<ObservablePoint>;
            var humidities = Program.Humidities as IList<ObservablePoint>;
            ObservablePoint? temperature = temperatures.LastOrDefault();
            ObservablePoint? humidity = humidities.LastOrDefault();
            if (temperature == null || humidity == null) return;

            var minute = temperature.X > humidity.X ? temperature.X : humidity.X;
            var timespan = TimeSpan.FromMinutes(minute);
            TotalTime = timespan;
            StartTime = DateTime.Now;
            EndTime = StartTime + timespan;

            Stopwatch stopwatch = Stopwatch.StartNew();
            Percent = 0;
            RoomMode = RoomMode.Running;

            //接续运行
            if (_startTime != null)
            {
                StartTime = _startTime.Value;
                EndTime = StartTime + timespan;
                TotalTime = timespan;
                OffsetTime = DateTime.Now - StartTime;
                newCurve = false;
                //加载曲线
                await InitCurve();
            }
            else
            {
                //记录缓存
                Cache.StartTime = StartTime;
                Cache.ProgramName = Program.Name;
                Cache.RoomMode = RoomMode;
                OffsetTime = TimeSpan.FromMinutes(0);
                newCurve = true;

            }
            await Task.Run(() =>
            {
                ThreadPool.QueueUserWorkItem(ShowCurve, stopwatch);//在线程池上运行一个子线程:实时显示曲线
                ThreadPool.QueueUserWorkItem(SaveCurve, stopwatch);//保存曲线
                while (RoomMode != RoomMode.Stopping && DateTime.Now <= EndTime)
                {
                    var timespan = stopwatch.Elapsed;
                    temperatureValue = Program.Temperatures.GetValue(timespan.TotalMinutes);
                    humidityValue = Program.Humidities.GetValue(timespan.TotalMinutes);
#if DEBUG
                    Percent = DateTime.Now.Second;
#else
                    Plc.Write($"{Address + 30}", temperatureValue);//写入温度预期值 
                    Plc.Write($"{Address + 31}", humidityValue);//写入湿度预期值 
                    Plc.Write($"{Address + 60}", RoomParameter.GetTemperatureParameters());//写入温度PID等参数
                    Plc.Write($"{Address + 70}", RoomParameter.GetHumidityParameters());//写入湿度PID等参数
                    Percent = (timespan.TotalMinutes / TotalTime.TotalMinutes);//进度条
#endif

                    Thread.Sleep(1000);//1秒钟写一次
                }

                if (DateTime.Now > EndTime)
                {
                    RoomMode = RoomMode.Stopping;
                    Cache.RoomMode = RoomMode.Stopping;
                }
            });


        }

        //加载上次中断的曲线数据，显示到LiveChart
        private Task InitCurve()
        {
            return Task.Run(() => 
            {
                var fullname = CurveHelper.GetLastCurveFullName(Id, StartTime, Cache.Csv);
                if (!File.Exists(fullname)) return;
                List<string> rows = File.ReadAllLines(fullname, Encoding.Default).ToList();
                if (rows == null || rows.Count <= 1)
                    return;
                rows.RemoveAt(0);//去掉字段
                try
                {
                    foreach (var row in rows)
                    {
                        string[] columns = row.Split(',');
                        if(columns==null|| columns.Length == 0) continue;
                        var success = double.TryParse(columns[1], out double x);
                        if (!success) continue;
                        var point0 = new ObservablePoint(x, double.Parse(columns[2]));
                        var point1 = new ObservablePoint(x, double.Parse(columns[3]));
                        var point2 = new ObservablePoint(x, double.Parse(columns[4]));
                        var point3 = new ObservablePoint(x, double.Parse(columns[5]));
                        var point4 = new ObservablePoint(x, double.Parse(columns[6]));
                        var point5 = new ObservablePoint(x, double.Parse(columns[7]));
                        var point6 = new ObservablePoint(x, double.Parse(columns[8]));
                        var point7 = new ObservablePoint(x, double.Parse(columns[9]));
                        var point8 = new ObservablePoint(x, double.Parse(columns[10]));
                        var point9 = new ObservablePoint(x, double.Parse(columns[11]));
                        var point10 = new ObservablePoint(x, double.Parse(columns[12]));
                        var point11 = new ObservablePoint(x, double.Parse(columns[13]));
                        var point12 = new ObservablePoint(x, double.Parse(columns[14]));
                        var point13 = new ObservablePoint(x, double.Parse(columns[15]));
                        System.Windows.Application.Current.Dispatcher.Invoke(() =>
                        {
                            Line0.Add(point0);
                            Line1.Add(point1);
                            Line2.Add(point2);
                            Line3.Add(point3);
                            Line4.Add(point4);
                            Line5.Add(point5);
                            Line6.Add(point6);
                            Line7.Add(point7);
                            Line8.Add(point8);
                            Line9.Add(point9);
                            Line10.Add(point10);
                            Line11.Add(point11);                            
                        });
                    }
                }
                catch(Exception ex)
                {
                    Logs.Error(ex);
                }
                
            });
        }

        /// <summary>
        /// 保存曲线
        /// </summary>
        /// <param name="state"></param>
        private void SaveCurve(object? state)
        {
            if (state == null) return;
            if (state is not Stopwatch stopwatch) return;
            string fullname = CurveHelper.GetCurveFullName(Id, StartTime, EndTime);
            string csvName = $"{StartTime.ToString("yyyyMMddHHmmss")}-{EndTime.ToString("yyyyMMddHHmmss")}";
            string column = $"序号,时间,{RoomParameter.TitleLine0},{RoomParameter.TitleLine1},{RoomParameter.TitleLine2},{RoomParameter.TitleLine3},{RoomParameter.TitleLine4},{RoomParameter.TitleLine5},{RoomParameter.TitleLine6},{RoomParameter.TitleLine7},{RoomParameter.TitleLine8},{RoomParameter.TitleLine0},{RoomParameter.TitleLine10},{RoomParameter.TitleLine11},温度,湿度\r";
            if (newCurve) 
            {
                File.AppendAllText(fullname, column, Encoding.Default);//列名
            }            
            Cache.Csv = csvName;
            int index = 1;
            while (RoomMode == RoomMode.Running)
            {
                string data = $"{index++},{stopwatch.Elapsed.Minutes + OffsetTime.Minutes},{Value0.Value},{Value1.Value},{Value2.Value},{Value3.Value},{Value4.Value},{Value5.Value},{Value6.Value},{Value7.Value},{Value8.Value},{Value9.Value},{Value10.Value},{Value11.Value},{temperatureValue / 10.0},{humidityValue / 10.0}\r";
                File.AppendAllText(fullname, data, Encoding.Default);//数据
                Cache.WriteTime = DateTime.Now;//更新最后一次写数据时间
                int sleep = 1000 * 60 * 5;
#if DEBUG
                sleep = 1000 * 5;
#endif
                Thread.Sleep(sleep);
            }

        }

        /// <summary>
        /// 显示曲线
        /// </summary>
        /// <param name="state"></param>
        private void ShowCurve(object? state)
        {
            if (state == null) return;
            if (state is not Stopwatch stopwatch) return;
            int step = 0;
            while (RoomMode == RoomMode.Running)
            {
                var timespan = stopwatch.Elapsed;
                System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => 
                {
                    Line0.Add(new ObservablePoint() { X = timespan.Minutes + OffsetTime.Minutes + step, Y = Value0.Value });
                    Line1.Add(new ObservablePoint() { X = timespan.Minutes + OffsetTime.Minutes, Y = Value1.Value });
                    Line2.Add(new ObservablePoint() { X = timespan.Minutes + OffsetTime.Minutes, Y = Value2.Value });
                    Line3.Add(new ObservablePoint() { X = timespan.Minutes + OffsetTime.Minutes, Y = Value3.Value });
                    Line4.Add(new ObservablePoint() { X = timespan.Minutes + OffsetTime.Minutes, Y = Value4.Value });
                    Line5.Add(new ObservablePoint() { X = timespan.Minutes + OffsetTime.Minutes, Y = Value5.Value });
                    Line6.Add(new ObservablePoint() { X = timespan.Minutes + OffsetTime.Minutes, Y = Value6.Value });
                    Line7.Add(new ObservablePoint() { X = timespan.Minutes + OffsetTime.Minutes, Y = Value7.Value });
                    Line8.Add(new ObservablePoint() { X = timespan.Minutes + OffsetTime.Minutes, Y = Value8.Value });
                    Line9.Add(new ObservablePoint() { X = timespan.Minutes + OffsetTime.Minutes, Y = Value9.Value });
                    Line10.Add(new ObservablePoint() { X = timespan.Minutes + OffsetTime.Minutes, Y = Value10.Value });
                    Line11.Add(new ObservablePoint() { X = timespan.Minutes + OffsetTime.Minutes, Y = Value11.Value });
                }));
#if DEBUG
                Thread.Sleep(1000);
                step += 5;
#else
                Thread.Sleep(1000 * 60 * 5);
#endif
            }
        }

        /// <summary>
        /// 停止运行
        /// </summary>
        /// <returns></returns>
        public async Task StopAsync()
        {
            await Task.Run(() =>
            {
                RoomMode = RoomMode.Stopping;
                Cache.RoomMode = RoomMode.Stopping;
            });
        }

        /// <summary>
        /// 解析100个点位
        /// </summary>
        /// <param name="array"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void Resolve(ushort[] array)
        {
            if (array == null || array.Length != 100)
                return;
            for (int i = 0; i < array.Length; i++)
            {
                Values[i].OriginValue = array[i];
                Values[i].Value = array[i] / 10.0;

#if DEBUG
                if (i == 18)
                {
                    Values[i].OriginValue = (ushort)(RoomMode == RoomMode.Running ? 1 : 0);
                    Values[i].Value = (ushort)(RoomMode == RoomMode.Running ? 1 : 0);
                }
                if (i == 30)
                {
                    Values[i].OriginValue = temperatureValue;
                    Values[i].Value = temperatureValue / 10.0;
                }
                if (i == 31)
                {
                    Values[i].OriginValue = humidityValue;
                    Values[i].Value = humidityValue / 10.0;
                }
#endif
            }
        }
    }
}
